/*************************************************************
   Copyright(C) 2017 by WuIslet
   All rights reserved.
   
   FindInPrefab.cs
   UnityFramework
   
   Created by WuIslet on 2018-02-01.
   
*************************************************************/
#if !USE_ILRUNTIME

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
//using UnityToolbarExtender.Examples;

public partial class FindInPrefab : EditorWindow
{
    class Phase<TI, TO>
    {
        virtual public void PreLoading() { }
        virtual public TO FuncReturn(TI input) { return default(TO); }
        virtual public void OnDraw() { }  // UI界面的绘制
        virtual public string CheckNeed(bool isSave, SearchRange sr, bool isDS, HitRule hr, AfterDeal ad) { return ""; } //确认前提条件
    }

    private class FindResult
    {
        public string type;
        public UnityEngine.Object rawObj;
        public GameObject go;
        public string name;
        public string path;
        public string extra; //中间过滤的额外数据
        public List<UnityEngine.Object> extraObjs; //中间过滤的额外数据
        public List<string> details; //打印统计使用，不要赋值

        public bool isGameObject()
        {
            return type == FIND_TYPE_GAMEOBJECT;
        }
    }
    #region 配置
    private const string ROOT_PATH = EditorPathConfig.UIPrefabModelRoot;
    private const string FORBID_UI_PATH = "";
    private const string SELF_PATH = "Assets/Scripts/CSharp/Framework/UI2/SuperPrefabFinder/Editor/FindInPrefab.cs";
    private const string RG_PATH = @"Tools\rg.exe";
    private const string RG_IGNORE_PATH = @"Tools\ignore.txt";
    private string printFileName = "FindResult";
    private const string subSeparatorChar = "/";
    private const string USE_EASY_MODE = "FindInPrefabEditor_USE_EASY_MODE";
    #endregion 配置

    Vector2 _scrollPos;
    Texture2D buttonTexture;
    private GUIStyle textAlignmentCenter;
    private static EditorWindow window;

    private bool _logFoldout = true;
    private static List<FindResult> mResultLog = new List<FindResult>();

    #region TAB
    string[] _tabLabels = new[] { "主要功能", "其他工具", };
    int _selectedTab;
    #endregion TAB

    [MenuItem("Tools/超级查找prefab")]
    static void Init()
    {
        window = window ?? EditorWindow.GetWindow<FindInPrefab>(true, "Prefab查找工具");
    }
    
    private static void ResetSetting()
    {
        mStep = 0;
        isUseEasyGuide = PlayerPrefs.GetInt(USE_EASY_MODE, 1) == 1;
        mIsSavePrefab = false;
        mIsDeepSearch = true;
        mResultLog.Clear();
        mSearchRange = SearchRange.查找文件夹;
        mHitRule = HitRule.含有Component;
        mAfterDeal = AfterDeal.打印详细;
        ResetSearchRange();
        ResetHitRule();
        ResetAfterDeal();
    }

    void OnGUI()
    {
        if (isUseEasyGuide)
        {
            DrawTab1Page();
        }
        else
        {
            #region TAB
            _selectedTab = GUILayout.Toolbar(_selectedTab, _tabLabels);
            #region 分割线
            GUILayout.Space(30f);
            Rect rect = GUILayoutUtility.GetLastRect();
            GUI.color = new Color(0.0f, 0.0f, 0.0f, 0.25f);
            GUI.DrawTexture(new Rect(0.0f, rect.yMin + 10.0f, Screen.width, 14.0f), EditorGUIUtility.whiteTexture);
            GUI.DrawTexture(new Rect(0.0f, rect.yMin + 10.0f, Screen.width, 1.0f), EditorGUIUtility.whiteTexture);
            GUI.DrawTexture(new Rect(0.0f, rect.yMin + 23.0f, Screen.width, 1.0f), EditorGUIUtility.whiteTexture);
            GUI.color = Color.white;
            #endregion 分割线
            switch (_selectedTab)
            {
                case 0:
                    DrawTab1Page();
                    break;
                case 1:
                    DrawTab2Page();
                    break;
                default:
                    DrawTab1Page();
                    break;
            }
            #endregion 分割线
        }

        DrawRightClick();
    }

    private void DrawTab1Page()
    {
        if (!isUseEasyGuide || mStep != 3) //简单模式下，查找结果界面不显示这个标题。
        {
            DrawFindGlobalSetting();
        }

        mCanNextStep = true;
        if (mStep == 0 || !isUseEasyGuide)
        {
            mCanNextStep &= DrawSearchRange();
        }
        if (mStep == 1 || !isUseEasyGuide)
        {
            mCanNextStep &= DrawHitRule();
        }
        if (mStep == 2 || !isUseEasyGuide)
        {
            mCanNextStep &= DrawAfterDeal();
            GUILayout.Space(20);
            if (!isUseEasyGuide && !mCanNextStep)
            {
                EditorGUILayout.HelpBox("条件有错误", MessageType.Error);
            }
            EditorGUI.BeginDisabledGroup(!mCanNextStep);
            if (GUILayout.Button("开始查找"))
            {
                mStep = 3;
                StartFind();
                //ResultLog_ShowInProjectWindow();
            }
            EditorGUI.EndDisabledGroup();
        }
        if (mStep == 3 || !isUseEasyGuide)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("输出文件", GUILayout.MaxWidth(50));
            printFileName = EditorGUILayout.TextField(printFileName, GUILayout.MaxWidth(200));
            if (GUILayout.Button("打印查找结果到文件"))
            {
                ResultLog_PrintToFile();
            }
            EditorGUILayout.EndHorizontal();

            //显示查找结果
            EditorGUILayout.BeginHorizontal();
            _logFoldout = EditorGUILayout.Foldout(_logFoldout, _logFoldout ? "收起" : "展开", true);
            if (mResultLog.Count > 0)
            {
                GUILayout.FlexibleSpace();
                EditorGUILayout.LabelField(string.Format("命中Prefab个数：{0}", mResultLog.Count), GUILayout.MaxWidth(200));
                var cnt = 0;
                foreach (var kv in mResultLog)
                {
                    cnt += kv.details.Count;
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.LabelField(string.Format("共命中{0}行", cnt), GUILayout.MaxWidth(100));
            }
            EditorGUILayout.EndHorizontal();

            if (_logFoldout)
            {
                if (mResultLog.Count <= 0)
                {
                    EditorGUILayout.TextArea("没有结果。");
                }
                else
                {
                    //GUIDrawScroll();
                    _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
                    ResultLog_ShowInEditorWindow();
                    EditorGUILayout.EndScrollView();
                }
            }
        }

        DrawEasyGuidePage();
    }

    private static bool mIsSavePrefab = false;
    private static bool mIsDeepSearch = true;
    private static int mStep = 0;
    private static bool mCanNextStep = true;
    private void DrawFindGlobalSetting()
    {
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.BeginHorizontal();
        mIsSavePrefab = GUILayout.Toggle(mIsSavePrefab, "是否要保存prefab的修改？");
        mIsDeepSearch = GUILayout.Toggle(mIsDeepSearch, "是否深度查找每个组件？");
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.EndVertical();

        if (isUseEasyGuide)
        {
            var title = "";
            switch (mStep)
            {
                case 0:
                    title = "步骤1：请选择查找的范围";
                    break;
                case 1:
                    title = "步骤2：请选择筛选条件";
                    break;
                case 2:
                    title = "步骤3：请决定找到之后的操作";
                    break;
            }

            if (!string.IsNullOrEmpty(title))
            {
                GUILayout.Label(title, EditorExtraStyles.HeadTitleStyle);
            }
        }
    }

    private void DrawEasyGuidePage()
    {
        GUILayout.FlexibleSpace();
        if (isUseEasyGuide)
        {
            if (!mCanNextStep)
            {
                EditorGUILayout.HelpBox("条件有错误", MessageType.Error);
            }

            EditorGUILayout.BeginHorizontal();
            if (0 <= mStep && mStep <= 2)
            {
                EditorGUI.BeginDisabledGroup(mStep < 1);
                if (GUILayout.Button("Prev"))
                {
                    --mStep;
                }
                EditorGUI.EndDisabledGroup();
                GUILayout.Label("步骤" + (mStep + 1) + "/3", GUI.skin.GetStyle("CenteredLabel"));
                EditorGUI.BeginDisabledGroup(mStep > 1 || !mCanNextStep);
                if (GUILayout.Button("Next"))
                {
                    ++mStep;
                }
            }
            else
            {
                if (GUILayout.Button(EditorGUIUtility.IconContent("Refresh")))
                {
                    mStep = 0;
                }
            }
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();
        }
    }

    private void DrawTab2Page()
    {
        DrawOtherTool();
    }

#if TestScroll
    MultiColumnHeaderState m_MultiColumnHeaderState;
    [SerializeField] TreeViewState m_TreeViewState;
    MultiColumnTreeView<object> m_SimpleTreeView;

    MultiColumnHeaderState.Column[] m_ColumnHeads = new MultiColumnHeaderState.Column[]
    {
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("Num"),
            headerTextAlignment = TextAlignment.Center,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Center,
            width = 200,
            minWidth = 60,
            autoResize = false,
            allowToggleVisibility = false
        },
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("100Num"),
            headerTextAlignment = TextAlignment.Left,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Left,
            width = 50,
            minWidth = 50,
            autoResize = true
        },
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("101Num"),
            headerTextAlignment = TextAlignment.Left,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Left,
            width = 50,
            minWidth = 50,
            autoResize = true
        },
    };
    
    void DoDrawCell(object item, Rect cellRect, int column)
    {
        if (item == null)
            return;
        var num = (int)item;
        var itemRect = new Rect(cellRect.x + 1, cellRect.y + 1, cellRect.width - 2, cellRect.height - 2);

        switch (column)
        {
            case 0:
                GUI.Label(itemRect, num.ToString());
                break;
            case 1:
                GUI.Label(itemRect, (num * 10).ToString());
                break;
            case 2:
                GUI.Label(itemRect, (num * 100 + num).ToString());
                break;
        }
    }

    private void OnEnable()
    {
        if (m_SimpleTreeView == null)
        {
            if (m_TreeViewState == null)
                m_TreeViewState = new TreeViewState();

            var MCHS = new MultiColumnHeaderState(m_ColumnHeads);
            if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, MCHS))
                MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, MCHS);

            m_MultiColumnHeaderState = MCHS;

            m_SimpleTreeView = new MultiColumnTreeView<object>(m_TreeViewState, new MultiColumnHeader(m_MultiColumnHeaderState), GetScrollData, DoDrawCell, 40);
        }
    }

    public object[] GetScrollData()
    {
        var list = new object[3000];
        for (int i = 0; i < 3000; ++i)
        {
            list[i] = i;
        }
        return list;
    }

    private void GUIDrawScroll()
    {
        m_SimpleTreeView.ReloadData();
        m_SimpleTreeView.OnGUI(new Rect(0, 100, 1000, 300));
    }
#endif

#region Scroll
    private MultiColumnHeaderState m_MultiColumnHeaderState;
    [SerializeField]
    private TreeViewState m_TreeViewState;
    private MultiColumnTreeView<FindResult> m_SimpleTreeView;

    private MultiColumnHeaderState.Column[] m_ColumnHeads = new MultiColumnHeaderState.Column[]
    {
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("图片"),
            headerTextAlignment = TextAlignment.Center,
            sortedAscending = false,
            sortingArrowAlignment = TextAlignment.Center,
            width = 150,
            minWidth = 60,
            autoResize = false,
            allowToggleVisibility = false
        },
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("名字"),
            headerTextAlignment = TextAlignment.Center,
            sortedAscending = false,
            sortingArrowAlignment = TextAlignment.Center,
            width = 200,
            minWidth = 60,
            autoResize = true
        },
        new MultiColumnHeaderState.Column
        {
            headerContent = new GUIContent("查找结果"),
            headerTextAlignment = TextAlignment.Center,
            sortedAscending = false,
            sortingArrowAlignment = TextAlignment.Center,
            width = 500,
            minWidth = 500,
            autoResize = true
        },
    };

    private void DoDrawCell(FindResult item, Rect cellRect, int column)
    {
        if (item == null)
            return;
        var itemRect = new Rect(cellRect.x + 1, cellRect.y + 1, cellRect.width - 2, cellRect.height - 2);
        
        switch (column)
        {
            case 0:
                var prefab = item.rawObj;
                if (AssetPreview.GetAssetPreview(prefab) == null)
                {
                    buttonTexture = AssetPreview.GetMiniThumbnail(prefab);
                }
                else
                {
                    buttonTexture = AssetPreview.GetAssetPreview(prefab);
                }
                
                if (GUI.Button(itemRect, buttonTexture))
                {
                    Selection.activeObject = prefab;
                    SceneView.RepaintAll();
                }
                break;
            case 1:
                var prefabName = item.name;
                Rect nameRect = new Rect(itemRect.x, itemRect.y, itemRect.width, 30);
                GUI.Label(nameRect, prefabName, textAlignmentCenter);
                Rect btnRect = new Rect(itemRect.x + 5, itemRect.y + 70, itemRect.width - 10, 30);
                if (GUI.Button(btnRect, "复制prefab名"))
                {
                    EditorGUIUtility.systemCopyBuffer = prefabName;
                    UnityEngine.Debug.Log(" 复制prefab名>> " + prefabName);
                }

                var sceneFullPath = Path.Combine(EditorPathConfig.UIPrefabModelRoot, prefabName + ".unity");
                if (!string.IsNullOrEmpty(prefabName) && File.Exists(sceneFullPath))
                {
                    if (GUI.Button(btnRect, "打开相关场景"))
                    {
                        EditorSceneHelper.StartScene(sceneFullPath, false);
                    }
                }
                break;
            case 2:
                StringBuilder sb = new StringBuilder();
                var list = item.details;
                for (int i = 0, len = list.Count; i < len; ++i)
                {
                    var line = list[i];
                    sb.AppendLine((i + 1) + ": " + line);
                }
                Rect lineRect = new Rect(itemRect.x, itemRect.y, itemRect.width, 30);
                GUI.Label(lineRect, string.Format("共{0}行", list.Count), textAlignmentCenter);
                Rect textRect = new Rect(itemRect.x, itemRect.y + 30, itemRect.width, itemRect.height - 30);
                GUI.TextArea(textRect, sb.ToString());
                break;
        }
    }

    private void OnEnable()
    {
        window = this;
        if (m_SimpleTreeView == null)
        {
            if (m_TreeViewState == null)
                m_TreeViewState = new TreeViewState();

            var MCHS = new MultiColumnHeaderState(m_ColumnHeads);
            if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, MCHS))
                MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, MCHS);

            m_MultiColumnHeaderState = MCHS;

            m_SimpleTreeView = new MultiColumnTreeView<FindResult>(m_TreeViewState, new MultiColumnHeader(m_MultiColumnHeaderState), GetScrollData, DoDrawCell, 200);
        }

        ResetSetting();
        textAlignmentCenter = new GUIStyle();
        textAlignmentCenter.alignment = TextAnchor.MiddleCenter;
        textAlignmentCenter.normal.textColor = Color.white;
        minSize = new Vector2(500f, 700f);

        InitRightMenu();
    }

    void OnDisable()
    {
        window = null;

        ClearRightMenu();
    }

    private FindResult[] GetScrollData()
    {
        var list = new FindResult[mResultLog.Count];
        for (int i = 0; i < mResultLog.Count; ++i)
        {
            list[i] = mResultLog[i];
        }
        return list;
    }

    private void GUIDrawScroll()
    {
        GUILayout.FlexibleSpace();
        Rect spaceRect = GUILayoutUtility.GetLastRect();
        m_SimpleTreeView.ReloadData();
        m_SimpleTreeView.OnGUI(new Rect(spaceRect.x, spaceRect.y, window.position.width, window.position.height - spaceRect.y));
    }
#endregion Scroll

    private static void StartFind()
    {
        mResultLog.Clear();
        UnityEngine.Debug.Log("开始查找.");
        SearchRangeClass[mSearchRange].PreLoading();
        HitRuleClass[mHitRule].PreLoading();
        AfterDealClass[mAfterDeal].PreLoading();

        Func<FindResult, bool> filter = null;
        if (mHitRule != HitRule.None)
        {
            filter = HitRuleClass[mHitRule].FuncReturn;
        }
        
        var searchResult = SearchRangeClass[mSearchRange].FuncReturn(null);
        foreach (var go in searchResult)
        {
            if (go.isGameObject() && mIsDeepSearch)
            {
                var isFind = false;
                List<string> onePrefabResult = new List<string>();
                var compList = BFSPrefab(go, filter);
                foreach (var fr in compList)
                {
                    var log = AfterDealClass[mAfterDeal].FuncReturn(fr);
                    if (!string.IsNullOrEmpty(log))
                    {
                        onePrefabResult.Add(log);
                        isFind = true;
                    }
                }

                if (isFind)
                {
                    go.details = onePrefabResult;
                    mResultLog.Add(go);
                }
            }
            else
            {
                if (!(filter == null || filter(go)))
                    continue;

                var log = AfterDealClass[mAfterDeal].FuncReturn(go);
                if (!string.IsNullOrEmpty(log))
                {
                    go.details = new List<string> { log };
                    mResultLog.Add(go);
                }
            }

            if (go.rawObj != null)
            {
                Undo.RegisterCompleteObjectUndo(go.rawObj, "FindInPrefab");

                if (mIsSavePrefab)
                {
                    EditorUtility.SetDirty(go.rawObj);
                }
            }
        }

        if (mIsSavePrefab)
        {
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
    }

    private static List<FindResult> BFSPrefab(FindResult go, Func<FindResult, bool> filter = null)
    {
        List<FindResult> result = new List<FindResult>();
        result.Add(go);
        int head = 0;
        int tail = 1;
        while (head != tail)
        {
            var curGo = result[head];
            head++;
            for (int i = 0; i < curGo.go.transform.childCount; ++i)
            {
                var childTr = curGo.go.transform.GetChild(i);
                var child = new FindResult
                {
                    type = FIND_TYPE_GAMEOBJECT,
                    go = childTr.gameObject,
                    name = childTr.name,
                    path = curGo.path + subSeparatorChar + childTr.name,
                };

                result.Add(child);
                tail++;
            }
        }

        if (filter != null)
        {
            for (int i = result.Count - 1; i >= 0; --i)
            {
                if (!filter(result[i]))
                {
                    result.RemoveAt(i);
                }
            }
        }

        return result;
    }

#region 处理输出
    private void ResultLog_PrintToFile()
    {
        if (mResultLog.Count == 0)
        {
            EditorUtility.DisplayDialog("提示", "没有查找结果", "OK");
            return;
        }

        if (!Directory.Exists(printFileName))
        {
            Directory.CreateDirectory(printFileName);
        }

        using (FileStream fs = new FileStream(printFileName + Path.DirectorySeparatorChar + printFileName + ".txt", FileMode.Create))
        {
            var sw = new StreamWriter(fs);
            foreach (var kv in mResultLog)
            {
                sw.WriteLine(kv.name);
                var list = kv.details;
                for (int i = 0, len = list.Count; i < len; ++i)
                {
                    var line = list[i];
                    sw.WriteLine("    |-> " + line);
                }
            }
            sw.Close();
        }
        string resultDir = Path.GetFullPath(printFileName) + Path.DirectorySeparatorChar;
        System.Diagnostics.Process.Start(resultDir);
    }

    private void ResultLog_ShowInProjectWindow()
    {
        if (mResultLog.Count > 0)
        {
            int[] findIds = new int[mResultLog.Count];
            int index = -1;
            foreach (var result in mResultLog)
            {
                var find = result.rawObj;
                findIds[++index] = find.GetInstanceID();
            }
            FilterShowAssets(findIds);
        }
    }

    private static void ResultLog_ShowInConsole()
    {
        UnityEngine.Debug.Log("============ Start Show Find Log ============");
        if (mResultLog.Count > 0)
        {
            foreach (var kv in mResultLog)
            {
                UnityEngine.Debug.Log(kv.name);
                var list = kv.details;
                for (int i = 0, len = list.Count; i < len; ++i)
                {
                    var line = list[i];
                    UnityEngine.Debug.Log("    |-> " + line);
                }
            }
        }
        else
        {
            UnityEngine.Debug.Log("没有结果");
        }
        UnityEngine.Debug.Log("============ End Show Find Log ============");
    }

    private static void ResultLog_ShowInEditorWindow()
    {
        foreach (var result in mResultLog)
        {
            StringBuilder sb = new StringBuilder();
            var list = result.details;
            var lineNo = 0;
            for (var len = list.Count; lineNo < len; ++lineNo)
            {
                var line = list[lineNo];
                sb.AppendLine((lineNo + 1) + ": " + line);
            }
            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(30);
            var prefabName = result.name;
            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.ObjectField(result.rawObj, typeof(UnityEngine.Object), true, GUILayout.Width(200));
            EditorGUI.EndDisabledGroup();

            EditorGUILayout.LabelField(string.Format("共{0}行", list.Count), GUILayout.MaxWidth(100));
            if (GUILayout.Button("复制prefab名", GUILayout.MaxWidth(100)))
            {
                EditorGUIUtility.systemCopyBuffer = prefabName;
                UnityEngine.Debug.Log(" 复制prefab名>> " + prefabName);
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal(); //TODO 增加折叠功能
            GUILayout.Space(60);
            EditorToolsUtils.DrawSelectableMultiLabel(sb.ToString(), lineNo);
            EditorGUILayout.EndHorizontal();
        }
    }
#endregion 处理输出

#region Tools
    /// <summary>
    /// Project中筛选显示指定的资源
    /// TwoColumns模式下，会将资源集中到一起；
    /// OneColumn模式下，仅选中资源。
    /// </summary>
    /// <param name="instanceIds">要显示的资源id，通过Object.GetInstanceID()获取</param>
    public static void FilterShowAssets(int[] instanceIds)
    {
        try
        {
            var t = typeof(ProjectWindowUtil);
            var obj = t.ReflectionPrivateStaticCall<object>("GetProjectBrowserIfExists");
            
            if (null != obj)
            {

                if (obj.ReflectionPrivateGetField<int>("m_ViewMode") == 1)
                {
                    obj.ReflectionPrivateCall<object, int[]>("ShowObjectsInList", instanceIds);
                    return;
                }
            }

            Selection.instanceIDs = instanceIds;
            //        _staticBrowser.CallPrivateStaticMethod("ShowSelectedObjectsInLastInteractedProjectBrowser");
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    /// <summary>
    /// 对外开放搜索功能
    /// </summary>
    /// <param name="way">1-当前场景的prefab，UI规范化。2-选中prefab，UI规范化。3-传入prefab，UI规范化。 //TODO 4-全局prefab，对于选中的查找引用 </param>
    public static void DoFindInPrefab(int way, GameObject target)
    {
        ResetSetting();
        if (way == 1)
        {
            mSearchRange = SearchRange.当前场景;
            mIsSavePrefab = true;
            mIsDeepSearch = true;
            mHitRule = HitRule.None;
            mAfterDeal = AfterDeal.UI规范化;
        }
        else if (way == 2)
        {
            mSearchRange = SearchRange.查找文件;
            var drag = SearchRangeClass[SearchRange.查找文件] as SearchFile;
            drag.SetTarget(Selection.activeGameObject);
            mIsSavePrefab = true;
            mIsDeepSearch = true;
            mHitRule = HitRule.None;
            mAfterDeal = AfterDeal.UI规范化;
        }
        else if (way == 3)
        {
            mSearchRange = SearchRange.查找文件;
            var drag = SearchRangeClass[SearchRange.查找文件] as SearchFile;
            drag.SetTarget(target);
            drag.SetExtension(FIND_TYPE_GAMEOBJECT);
            mIsSavePrefab = true;
            mIsDeepSearch = true;
            mHitRule = HitRule.None;
            mAfterDeal = AfterDeal.UI规范化;
        }
        else
            return;

        StartFind();
        ResultLog_ShowInConsole();
    }
    
    [MenuItem("GameObject/UI规范化", priority = 0)]
    public static void DoUIFormat()
    {
        DoFindInPrefab(2, null);
    }

    public static List<string> SearchWithRG(string keyword, bool isReg, bool isWord)
    {
        int totalWaitMilliseconds = 300 * 1000;
        var references = new List<string>();
        var appDataPath = Application.dataPath;
        var cpuCount = Environment.ProcessorCount;
        var psi = new ProcessStartInfo();
        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            psi.FileName = "/usr/bin/mdfind";
            psi.Arguments = string.Format("-onlyin {0} {1}", appDataPath, keyword);
            totalWaitMilliseconds = 2 * 1000;
        }
        else
        {
            psi.FileName = Path.Combine(Environment.CurrentDirectory, @"Tools\rg.exe");
            psi.Arguments = string.Format("--case-sensitive --follow --files-with-matches --no-text " +
                                          (isReg ? "" : "--fixed-strings ") +
                                          (isWord ? "-w " : "") +
                                          "--ignore-file Tools/rgIgnore.txt " +
                                          "--threads {0} --regexp {1} -- {2}",
                cpuCount, keyword, appDataPath);
        }

        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;
        psi.CreateNoWindow = true;

        var process = new Process();
        process.StartInfo = psi;

        process.OutputDataReceived += (sender, e) =>
        {
            if (string.IsNullOrEmpty(e.Data))
                return;

            string relativePath = e.Data.Replace(appDataPath, "Assets").Replace("\\", "/");
            references.Add(relativePath);
        };

        process.ErrorDataReceived += (sender, e) =>
        {
            if (string.IsNullOrEmpty(e.Data))
                return;
        };

        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        var stopwatch = new Stopwatch();
        stopwatch.Start();
        while (!process.HasExited)
        {
            if (stopwatch.ElapsedMilliseconds < totalWaitMilliseconds)
            {
                float progress = (float)((double)stopwatch.ElapsedMilliseconds / totalWaitMilliseconds);
                string info = string.Format("Finding {0}/{1}s {2:P2}", stopwatch.ElapsedMilliseconds / 1000,
                    totalWaitMilliseconds / 1000, progress);
                bool canceled = EditorUtility.DisplayCancelableProgressBar("Find References in Project", info, progress);

                if (canceled)
                {
                    process.Kill();
                    break;
                }

                Thread.Sleep(100);
            }
            else
            {
                process.Kill();
                break;
            }
        }


        EditorUtility.ClearProgressBar();
        stopwatch.Stop();
        return references;
    }

    public const string FIND_TYPE_OBJECT = "object"; //TODO 扩展 文件类型
    public const string FIND_TYPE_GAMEOBJECT = "gameObject";
    private static string GetTypeWithExtension(string extension)
    {
        switch (extension)
        {
            case ".prefab":
                return FIND_TYPE_GAMEOBJECT;
            case ".asset":
                return "scriptableObject";
            case ".controller":
                return "animatorcontroller";
            case ".ttf":
                return "font";
            default:
                return FIND_TYPE_OBJECT;
        }
    }
#endregion Tools

#region RightClick
    public static bool isUseEasyGuide = true;
    private GenericMenu RightMenu;
    private void InitRightMenu()
    {
        RightMenu = new GenericMenu();
        RightMenu.AddItem(new GUIContent("简单引导模式"), isUseEasyGuide, TagMenuClick);
        RightMenu.AddSeparator("");
        RightMenu.AddItem(new GUIContent("打开工具代码"), false, OpenEditorWindowCode);
    }
    private void ClearRightMenu()
    {

    }

    private void DrawRightClick()
    {
        if (Event.current.type == UnityEngine.EventType.ContextClick)
        {
            RightMenu?.ShowAsContext();
            Event.current.Use();
        }
    }

    private void TagMenuClick()
    {
        isUseEasyGuide = !isUseEasyGuide;
        mStep = 0;
        _selectedTab = 0;
        PlayerPrefs.SetInt(USE_EASY_MODE, isUseEasyGuide ? 1 : 0);
        InitRightMenu();
    }

    private void OpenEditorWindowCode()
    {
        var asset = AssetDatabase.LoadMainAssetAtPath(SELF_PATH);
        AssetDatabase.OpenAsset(asset, 0);
    }
#endregion RightClick

}
#endif